$:.unshift File.join(File.dirname(__FILE__),'../..','src')

# Represents a ship game piece.  These pieces will be placed on each players
# grids and will then be shot at.  Each ship must track its status (if it is
# still alive or not) as well as be aware of its size and orientation so that
# the grid can place it correctly.

# Ships are made up of a series of ShipCompartment objects, with the number of
# compartments representing the ship's size.  If all compartments of a ship are
# hit, then the ship is dead.

# There are five kinds of ship, and each player has one of each on their grid.
# As a convenience, and to reduce errors, the Ship class does not expose its raw
# constructor.  Instead ship types are constructed via specific creator methods.
# The five ship types and their sizes are listed below.
# * Patrol Boat - two compartments
# * Submarine - three compartments
# * Destroyer - three compartments
# * Cruiser - four compartments
# * Carrier - five compartments
class Ship

  private_class_method :new

  # Gets or sets the orientation of the ship.  This is a single character, with
  # 'h' representing horozontal orientation, and 'v' representing vertical
  # orientation.  Orientation is specified relative to the grid.
  attr :orientation, true

  def initialize(name, size, orientation = 'v')
    raise 'Orientation must be vertical (v) or horozontal (h)' unless orientation == 'v' or orientation == 'h'
		@orientation = orientation
		@ship_name = name
		@hull = Array.new
		(1..size).each { |i| @hull << ShipCompartment.new(i - 1) }
	end

  # Creates a new patrol boat Ship instance, which consists of two compartments.
  # The default orientation is vertical.
  public
  def Ship.create_patrol_boat(orientation = 'v')
    new('Patrol Boat', 2, orientation)
  end

  # Creates a new submarine Ship instance, which consits of three compartments.
  # The default orientation is vertical.
  public
  def Ship.create_submarine(orientation = 'v')
    new('Submarine', 3, orientation)
  end

  # Creates a new destroyer Ship instnace, which consists of three compartments.
  # The default orientation is vertical.
  public
  def Ship.create_destroyer(orientation = 'v')
    new('Destroyer', 3, orientation)
  end

  # Creates a new cruiser Ship instance, which consists of four compartments.
  # The default orientation is vertical.
  public
  def Ship.create_cruiser(orientation = 'v')
    new('Cruiser', 4, orientation)
  end

  # Creates a new carrier Ship instance, which consists of five compartments.
  # The default orientation is vertical.
  public
  def Ship.create_carrier(orientation = 'v')
    new('Carrier', 5, orientation)
  end

  # Gets the width of the ship - that is the number of squares it will take up
  # across the x axis of a grid.  This value is orientation sensistive.
  public
	def width
		if (@orientation == 'h') then return @hull.length else return 1 end
	end

  # Gets the height of the ship - that is the number of squares it will take up
  # across the Y axis of a grid.  This value is orientation sensistive.
  public
	def height
		if (@orientation == 'v') then return @hull.length else return 1 end
	end

  # Determines if the ship is alive.  It is alive if at least one compartment is
  # still alive (as determined by the ShipCompartment#alive? method).
  public
	def alive?
		is_alive = @hull.any? { |c| c.alive? }
		return is_alive
	end

  # Iterates over the ShipCompartment objects that make up the Ship instance.
  public
  def each
    @hull.each { |item| yield item }
  end

  # Retrieves a ShipCompartment object at the specified compartment index.
  public
  def [] (index)
    @hull[index]
  end
  
end